home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wprogressindicator.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-09  |  7.2 KB  |  299 lines

  1. /*
  2.  * Original idea and implementation by Frederik Schueler <fr.schueler@netsurf.de>
  3.  * Rewritten by Pascal Hofstee <daeron@windowmaker.org>
  4.  * - Added options to set min/max values
  5.  * - centralized drawing into one pain function
  6.  */
  7.  
  8. #include "WINGsP.h"
  9.  
  10. typedef struct W_ProgressIndicator {
  11.     W_Class    widgetClass;
  12.     W_View    *view;
  13.     
  14.     int    value;
  15.     int    minValue;
  16.     int    maxValue;
  17.     
  18.     void    *clientData;
  19. } ProgressIndicator;
  20.  
  21.  
  22. #define DEFAULT_PROGRESS_INDICATOR_WIDTH    276
  23. #define DEFAULT_PROGRESS_INDICATOR_HEIGHT    16
  24.  
  25. /* define if only the ticks within the progress region should be displayed */
  26. #define SHOW_PROGRESS_TICKS_ONLY
  27.  
  28.  
  29. static void didResizeProgressIndicator();
  30.  
  31.  
  32. W_ViewDelegate _ProgressIndicatorDelegate = {
  33.     NULL,
  34.     NULL,
  35.     didResizeProgressIndicator,
  36.     NULL,
  37.     NULL
  38. };
  39.  
  40.  
  41. static void destroyProgressIndicator(ProgressIndicator *pPtr);
  42. static void paintProgressIndicator(ProgressIndicator *pPtr);
  43. static void realizeProgressIndicator(ProgressIndicator *pPtr);
  44. static void handleEvents(XEvent *event, void *data);
  45.  
  46. static void realizeObserver(void *self, WMNotification *not) {
  47.     
  48.     realizeProgressIndicator(self);
  49. }
  50.  
  51.  
  52.  
  53. WMProgressIndicator*
  54.     WMCreateProgressIndicator(WMWidget *parent)
  55. {
  56.     ProgressIndicator *pPtr;
  57.     
  58.     pPtr = wmalloc(sizeof(ProgressIndicator));
  59.     memset(pPtr, 0, sizeof(ProgressIndicator));
  60.     
  61.     pPtr->widgetClass = WC_ProgressIndicator;
  62.     
  63.     pPtr->view = W_CreateView(W_VIEW(parent));
  64.     if (!pPtr->view) {
  65.     wfree(pPtr);
  66.     return NULL;
  67.     }
  68.     
  69.     pPtr->view->self = pPtr;
  70.     
  71.     pPtr->view->delegate = &_ProgressIndicatorDelegate;
  72.     
  73.     WMCreateEventHandler(pPtr->view, ExposureMask|StructureNotifyMask,
  74.              handleEvents, pPtr);
  75.     
  76.     
  77.     W_ResizeView(pPtr->view, DEFAULT_PROGRESS_INDICATOR_WIDTH,
  78.          DEFAULT_PROGRESS_INDICATOR_HEIGHT);
  79.     
  80.     /* Initialize ProgressIndicator Values */
  81.     pPtr->value = 0;
  82.     pPtr->minValue = 0;
  83.     pPtr->maxValue = 100;
  84.     
  85.     WMAddNotificationObserver(realizeObserver, pPtr,
  86.                   WMViewRealizedNotification, pPtr->view);
  87.     
  88.     return pPtr;
  89. }
  90.  
  91.  
  92. void
  93. WMSetProgressIndicatorMinValue(WMProgressIndicator *progressindicator, int value)
  94. {
  95.     CHECK_CLASS(progressindicator, WC_ProgressIndicator);
  96.     
  97.     progressindicator->minValue = value;
  98.     if (progressindicator->value < value) {
  99.     progressindicator->value = value;
  100.     if (progressindicator->view->flags.mapped) {
  101.         paintProgressIndicator(progressindicator);
  102.     }
  103.     }
  104. }
  105.  
  106.  
  107. void
  108. WMSetProgressIndicatorMaxValue(WMProgressIndicator *progressindicator, int value)
  109. {
  110.     CHECK_CLASS(progressindicator, WC_ProgressIndicator);
  111.     
  112.     progressindicator->maxValue = value;
  113.     if (progressindicator->value > value) {
  114.     progressindicator->value = value;
  115.     if (progressindicator->view->flags.mapped) {
  116.         paintProgressIndicator(progressindicator);
  117.     }
  118.     }
  119. }
  120.  
  121.  
  122. void
  123. WMSetProgressIndicatorValue(WMProgressIndicator *progressindicator, int value)
  124. {
  125.     CHECK_CLASS(progressindicator, WC_ProgressIndicator);
  126.     
  127.     progressindicator->value = value;
  128.     
  129.     /* Check if value is within min/max-range */
  130.     if (progressindicator->minValue > value)
  131.     progressindicator->value = progressindicator->minValue;
  132.     
  133.     if (progressindicator->maxValue < value)
  134.     progressindicator->value = progressindicator->maxValue;
  135.     
  136.     
  137.     if (progressindicator->view->flags.mapped) {
  138.     paintProgressIndicator(progressindicator);
  139.     }
  140. }
  141.  
  142.  
  143. int
  144. WMGetProgressIndicatorMinValue(WMProgressIndicator *progressindicator)
  145. {
  146.     CHECK_CLASS(progressindicator, WC_ProgressIndicator);
  147.     
  148.     return progressindicator->minValue;
  149. }
  150.  
  151.  
  152. int
  153. WMGetProgressIndicatorMaxValue(WMProgressIndicator *progressindicator)
  154. {
  155.     CHECK_CLASS(progressindicator, WC_ProgressIndicator);
  156.     
  157.     return progressindicator->maxValue;
  158. }
  159.  
  160.  
  161. int
  162. WMGetProgressIndicatorValue(WMProgressIndicator *progressindicator)
  163. {
  164.     CHECK_CLASS(progressindicator, WC_ProgressIndicator);
  165.     
  166.     return progressindicator->value;
  167. }
  168.  
  169.  
  170. static void
  171. realizeProgressIndicator(ProgressIndicator *pPtr)
  172. {
  173.     W_RealizeView(pPtr->view);
  174. }
  175.  
  176.  
  177. static void
  178. didResizeProgressIndicator(W_ViewDelegate *self, WMView *view)
  179. {
  180.     WMProgressIndicator *pPtr = (WMProgressIndicator*)view->self;
  181.     int width = pPtr->view->size.width;
  182.     int height = pPtr->view->size.height;
  183.     
  184.     assert(width > 0);
  185.     assert(height > 0);
  186. }
  187.  
  188.  
  189. static void
  190. paintProgressIndicator(ProgressIndicator *pPtr)
  191. {
  192.     W_Screen *scr = pPtr->view->screen;
  193.     GC bgc;
  194.     GC wgc;
  195.     GC lgc;
  196.     GC dgc;
  197.     WMSize size = pPtr->view->size;
  198.     int perc, w, h;
  199.     double unit, i;
  200.     Pixmap buffer;
  201.     
  202.     bgc = WMColorGC(scr->black);
  203.     wgc = WMColorGC(scr->white);
  204.     lgc = WMColorGC(scr->gray);
  205.     dgc = WMColorGC(scr->darkGray);
  206.     
  207.     unit = (double)(size.width - 3.0) / 100;
  208.     
  209.     buffer = XCreatePixmap(scr->display, pPtr->view->window, 
  210.                size.width, size.height, scr->depth);
  211.     
  212.     XFillRectangle(scr->display, buffer, lgc, 0, 0, size.width, size.height);
  213.     
  214.     /* Calculate size of Progress to draw and paint ticks*/
  215.     perc = (pPtr->value - pPtr->minValue) * 100 / (pPtr->maxValue - pPtr->minValue);
  216.     
  217.     w = (int)((double)(perc * unit));
  218.     h = size.height - 2;
  219.     
  220.     if (w > (size.width - 3))
  221.     w = size.width - 3;
  222.     
  223.     if (w > 0) {
  224.     XFillRectangle(scr->display, buffer, lgc, 2, 1, w, h);
  225.     XFillRectangle(scr->display, buffer, scr->stippleGC, 2, 1, w, h);
  226.     W_DrawRelief(scr, buffer, 2, 1, w, h, WRFlat);
  227.     
  228.     /* Draw Progress Marks */
  229.     i=(5.0*unit);
  230.     
  231. #ifdef SHOW_PROGRESS_TICKS_ONLY
  232.     while((int)i<w+5) {
  233. #else
  234.     while ((int)i < (size.width - 3)) {
  235. #endif
  236.         XDrawLine(scr->display, buffer, dgc, (int)i+2, h-1, i+2, h-3);
  237.         
  238.         i+=(5.0*unit);
  239.         
  240. #ifdef SHOW_PROGRESS_TICKS_ONLY
  241.         if((int)i>=w)
  242.         break;
  243. #endif
  244.         
  245.         XDrawLine(scr->display, buffer, dgc, (int)i+2, h-1, i+2, h-6);
  246.         
  247.         i+=(5.0*unit);
  248.     }
  249.     }
  250.     
  251.     XDrawLine(scr->display, buffer, bgc, w+2, 1, w+2, h+1);
  252.     XDrawLine(scr->display, buffer, lgc, 2, h, w+2, h);
  253.     
  254.     
  255.     XDrawLine(scr->display, buffer, dgc, 0, 0, 0, size.height-1);
  256.     XDrawLine(scr->display, buffer, dgc, 0, 0, size.width, 0);
  257.     XDrawLine(scr->display, buffer, bgc, 1, 1, 1, size.height-1);
  258.     XDrawLine(scr->display, buffer, bgc, 1, 1, size.width-1, 1);
  259.     
  260.     XDrawLine(scr->display, buffer, wgc, size.width-1, 0,
  261.           size.width-1, size.height-1);
  262.     XDrawLine(scr->display, buffer, wgc, 0, size.height-1,
  263.           size.width-1, size.height-1);
  264.     
  265.     XCopyArea(scr->display, buffer, pPtr->view->window, scr->copyGC, 0, 0,
  266.           size.width, size.height, 0, 0);
  267.     
  268.     XFreePixmap(scr->display, buffer);
  269. }
  270.  
  271. static void
  272. handleEvents(XEvent *event, void *data)
  273. {
  274.     ProgressIndicator *pPtr = (ProgressIndicator*)data;
  275.     
  276.     CHECK_CLASS(data, WC_ProgressIndicator);
  277.     
  278.     switch (event->type) {
  279.      case Expose:
  280.     if (event->xexpose.count!=0)
  281.         break;
  282.     paintProgressIndicator(pPtr);
  283.     break;
  284.      case DestroyNotify:
  285.     destroyProgressIndicator(pPtr);
  286.     break;
  287.     }
  288. }
  289.  
  290.  
  291. static void
  292. destroyProgressIndicator(ProgressIndicator *pPtr)
  293. {
  294.     WMRemoveNotificationObserver(pPtr);
  295.     
  296.     wfree(pPtr);
  297. }
  298.  
  299.